//
//  AppController.m
//  EVE Mac Suite
//
//  Created by Vadim Lozko on 2/6/09.
//  Copyright 2009 __Vadim__. All rights reserved.
//

#import "EMSAppController.h"
#import "EMSGeneralUtils.h"
#import "EMSAppInitializer.h"
#import "EVEAPIDownloader.h"
#import "EVEAPICoreDataController.h"
#import	"EMSCharactersWindowController.h"
#import "EMSCharacterViewController.h"
#import "EMSCharacterDataController.h"
#import "EMSPreferencesWindowController.h"
#import "EVECDCharacter.h"
#import "EVECDServer.h"

@interface EMSAppController (privateMethods)

-(void)startProgressBarWindowWithText:(NSString*)text;

@end

@implementation EMSAppController

@synthesize characterControllers;
@synthesize selectedCharacterController;
@synthesize server;

-(void)awakeFromNib
{
	NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
	[defaultCenter addObserver:self
					  selector:@selector(willUpdateSkillTree:)
						  name:WILL_UPDATE_SKILL_TREE_NOTIFICATION_NAME 
						object:nil];
	[defaultCenter addObserver:self 
					  selector:@selector(skillTreeUpdateDidFinish:) 
						  name:SKILL_TREE_API_TYPE
						object:nil];
	[defaultCenter addObserver:self
					  selector:@selector(finishedUpdatingCharacters:) 
						  name:DID_UPDATE_ALL_CHARACTERS_NOTIFICATION_NAME 
						object:nil];
	[defaultCenter addObserver:self 
					  selector:@selector(updateServerStatus:) 
						  name:SERVER_STATUS_API_TYPE 
						object:nil];
	characterControllers = [[NSMutableSet alloc] init];
	EMSAppInitializer* initializer = [[EMSAppInitializer alloc] initWithAppController:self];
	[initializer start];
}

-(void)dealloc
{
	[characterControllers release];
	[super dealloc];
}

-(EMSCharacterViewController*)selectedCharacterController
{
	if([[characterControllerArrayController selectedObjects] count] == 1)
	{
		return [[characterControllerArrayController selectedObjects] objectAtIndex:0];
	} else {
		return nil;
	}
}

#pragma mark Character Management

-(void)createNewCharacterFromInfo:(NSDictionary*)infoDict
{	
	NSDictionary* charInfoDictionary = [infoDict copy];
	NSExpression* existingCharacterNamesExpression = [NSExpression expressionForKeyPath:@"character.name"];
	NSArray* existingCharacterNames = [existingCharacterNamesExpression expressionValueWithObject:characterControllers context:nil];
	if(![existingCharacterNames containsObject:[charInfoDictionary objectForKey:CHAR_INFO_DICT_NAME]])
	{
		EMSCharacterViewController* newCharacterViewController = [[EMSCharacterViewController alloc] initWithCharacterInfo:charInfoDictionary];
		newCharacterViewController.delegate = self;
		[[NSUserDefaults standardUserDefaults] setObject:[charInfoDictionary objectForKey:CHAR_INFO_DICT_NAME] 
												  forKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY];
	} else {
		//TODO: Add character already exists notification.
	}
}

-(void)didLoadCharacterViewController:(EMSCharacterViewController*)controller
{
	NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
	NSDictionary* charInfoDictionary = [[controller dataController] characterInfo];
	if([defaults arrayForKey:USER_DEFAULTS_CHARACTERS_KEY])
	{
		NSMutableArray* defaultsCharactersArray = [[defaults arrayForKey:USER_DEFAULTS_CHARACTERS_KEY] mutableCopy];
		int i;
		for(i = 0; i < [defaultsCharactersArray count]; i++)
		{
			NSDictionary* existingCharDict = [defaultsCharactersArray objectAtIndex:i];
			if([[existingCharDict objectForKey:CHAR_INFO_DICT_NAME] isEqualToString:
				[charInfoDictionary objectForKey:CHAR_INFO_DICT_NAME]])
			{
				[defaultsCharactersArray removeObject:existingCharDict];
			}
		}
		[defaultsCharactersArray addObject:charInfoDictionary];
		[defaults setObject:defaultsCharactersArray forKey:USER_DEFAULTS_CHARACTERS_KEY];
		[defaultsCharactersArray release];
	} else {
		NSArray* newCharacterArray = [NSArray arrayWithObject:charInfoDictionary];
		[defaults setObject:newCharacterArray forKey:USER_DEFAULTS_CHARACTERS_KEY];
	}
	[defaults synchronize];
	[self willChangeValueForKey:@"characterControllers"];
	[self.characterControllers addObject:controller];
	[self didChangeValueForKey:@"characterControllers"];
	[controller release];
	if([[defaults stringForKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY] isEqualToString:[controller charName]])
	{
		//[characterControllerArrayController setSelectedObjects:[NSArray arrayWithObject:controller]];
		//[charactersPopUpButton selectItemWithTitle:[controller charName]];
	}
}

-(void)addNewCharacterWindowDidCancel
{
	
}

-(IBAction)createNewCharacter:(id)sender
{
	[EMSCharactersWindowController controller].delegate = self;
}

-(IBAction)selectCharacter:(id)sender
{
	NSString* characterName = [(NSPopUpButton*)sender titleOfSelectedItem];
	if([self selectedCharacterController] && ![[[self selectedCharacterController] charName] isEqualToString:characterName])
	{
		//Should only be one object, I hope...
		EMSCharacterViewController* replacementViewController = [[self.characterControllers filteredSetUsingPredicate:
																  [NSPredicate predicateWithFormat:@"character.name like %@", characterName]] anyObject];
		[characterControllerArrayController setSelectedObjects:[NSArray arrayWithObject:replacementViewController]];
		//[charactersPopUpButton selectItemWithTitle:characterName];
		[[NSUserDefaults standardUserDefaults] setObject:characterName
											  forKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY];
		[[NSUserDefaults standardUserDefaults] synchronize];
	}
}

-(IBAction)showMainWindow:(id)sender
{
	[mainWindow makeKeyAndOrderFront:nil];
}

-(IBAction)saveContext:(id)sender
{
	[[EVEAPICoreDataController coreDataController] saveData];
}

-(IBAction)openPreferences:(id)sender
{
	[[[EMSPreferencesWindowController sharedController] window] makeKeyAndOrderFront:nil];
}

-(IBAction)cancelDownload:(id)sender
{
	[[EVEAPIDownloader sharedDownloader] cancelDownload];
	[updateInProgressProgressIndicator stopAnimation:nil];
	[updateInProgressWindow orderOut:nil];
	[NSApp endSheet:updateInProgressWindow];
}

-(NSManagedObjectContext*)managedObjectContext
{
	return EVECDContext;
}

-(void)updateServerStatus:(NSNotification*)notification
{
	if([[[notification userInfo] objectForKey:NOTIFICATION_SUCCESS_UPDATE_KEY] boolValue])
	{
		if(!self.server)
		{
			self.server = (EVECDServer*)[EVECDContext fetchObjectForEntityName:@"EVECDServer" withPredicate:nil];
		}
	}
}

-(void)willUpdateSkillTree:(NSNotification*)notification
{
	[self startProgressBarWindowWithText:@"Building database for first time use."];
}

-(void)skillTreeUpdateDidFinish:(NSNotification*)notification
{
	[updateInProgressTextField setStringValue:@"Updating Characters"];
}

-(void)finishedUpdatingCharacters:(NSNotification*)notification
{
	NSString* defaultCharacterName = [[NSUserDefaults standardUserDefaults] stringForKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY];
	if(defaultCharacterName)
	{
		NSArray* existingCharacterControllers = [[self.characterControllers filteredSetUsingPredicate:
												  [NSPredicate predicateWithFormat:@"character.name like %@", defaultCharacterName]] allObjects];
		
		if([existingCharacterControllers count] == 1)
		{
			[characterControllerArrayController setSelectedObjects:[NSArray arrayWithObject:[existingCharacterControllers objectAtIndex:1]]];
		}
	}
	[updateInProgressProgressIndicator stopAnimation:nil];
	[updateInProgressWindow orderOut:nil];
	[NSApp endSheet:updateInProgressWindow];
}


-(void)removeCharacter
{
	EMSCharacterViewController* selectedController = [self selectedCharacterController];
	if(selectedController)
	{
		NSDictionary* charInfoDictionary = [[selectedController dataController] characterInfo];
		NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
		if([defaults arrayForKey:USER_DEFAULTS_CHARACTERS_KEY])	//No reason it should be no.
		{
			NSMutableArray* defaultsCharactersArray = [[defaults arrayForKey:USER_DEFAULTS_CHARACTERS_KEY] mutableCopy];
			int i;
			for(i = 0; i < [defaultsCharactersArray count]; i++)
			{
				NSDictionary* existingCharDict = [defaultsCharactersArray objectAtIndex:i];
				if([[existingCharDict objectForKey:CHAR_INFO_DICT_NAME] isEqualToString:
					[charInfoDictionary objectForKey:CHAR_INFO_DICT_NAME]])
				{
					[defaultsCharactersArray removeObject:existingCharDict];
				}
			}
			[defaults removeObjectForKey:USER_DEFAULTS_CHARACTERS_KEY];
			[defaults setObject:defaultsCharactersArray forKey:USER_DEFAULTS_CHARACTERS_KEY];
			[defaultsCharactersArray release];
		}
		
		[self willChangeValueForKey:@"characterControllers"];
		[self.characterControllers removeObject:selectedController];
		[self didChangeValueForKey:@"characterControllers"];
		
		EMSCharacterViewController* selectedController = [self selectedCharacterController];
		if(selectedController)
		{
			//[charactersPopUpButton selectItemWithTitle:[selectedController charName]];
			[defaults setObject:[selectedController charName] forKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY];
		} else {
			//[charactersPopUpButton removeAllItems];
			[defaults removeObjectForKey:USER_DEFAULTS_PREFERED_CHARACTER_KEY];
		}
		[defaults synchronize];
	}
}

-(void)resetAndRestart
{
	//$N = argv[N]
	NSString *killArg1AndOpenArg2Script = @"kill -9 $1 \n open \"$2\"";
	
	//NSTask needs its arguments to be strings
	NSString *ourPID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];
	
	//this will be the path to the .app bundle,
	//not the executable inside it; exactly what `open` wants
	NSString * pathToUs = [[NSBundle mainBundle] bundlePath];
	
	NSArray *shArgs = [NSArray arrayWithObjects:@"-c", // -c tells sh to execute the next argument, passing it the remaining arguments.
					   killArg1AndOpenArg2Script,
					   @"", //$0 path to script (ignored)
					   ourPID, //$1 in restartScript
					   pathToUs, //$2 in the restartScript
					   nil];
	[[NSFileManager defaultManager] removeFileAtPath:[EMSGeneralUtils applicationSupportFolder] handler:nil];
	NSTask *restartTask = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:shArgs];
	[restartTask waitUntilExit]; //wait for killArg1AndOpenArg2Script to finish
	NSLog(@"*** ERROR: %@ should have been terminated, but we are still running", pathToUs);
	assert(!"We should not be running!");	
}

@end

@implementation EMSAppController (privateMethods)

-(void)startProgressBarWindowWithText:(NSString*)text
{
	[NSApp beginSheet:updateInProgressWindow modalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil];
	[updateInProgressTextField setStringValue:text];
	[updateInProgressProgressIndicator setUsesThreadedAnimation:YES];
	[updateInProgressProgressIndicator startAnimation:nil];
}



@end

